#pragma once

#include "e2d/core/pch.h"
#include "e2d/core/Scene.h"

namespace e2d
{

	struct EntityHandler
	{
		std::shared_ptr<e2d::Scene> m_Scene;

		void SetInst(std::shared_ptr<e2d::Scene> scene)
		{
			m_Scene = scene;
		}

		virtual void OnLoad() {};

		virtual void OnLoadRuntime() {};

		virtual void OnUpdate() {};

		virtual void OnUpdateRuntime() {};

		virtual void OnRender() {}

		virtual void OnRenderRuntime() {};

		virtual void OnStart() {}

		virtual void OnDestory() {}

		template<typename T>
		void LoadView(std::function<bool(const e2d::Entity&)> func = 0)
		{
			auto view = m_Scene->rg.view<T>();
			for (auto e : view)
			{
				auto& t = m_Scene->rg.get<T>(e);

				bool filter = true;
				if (func)
				{
					if (t.m_Entity)
					{
						filter = func(*t.m_Entity);
					}
				}
				if (filter)
				{
					t.OnLoad();
				}
			}
		}

		template<typename T>
		void UpdateView(std::function<bool(const e2d::Entity&)> func = 0)
		{
			auto view = m_Scene->rg.view<T>();
			for (auto e : view)
			{

				auto& t = m_Scene->rg.get<T>(e);


				bool filter = true;
				if (func)
				{
					if (t.m_Entity)
					{
						filter = func(*t.m_Entity);
					}
				}

				if (filter)
					t.OnUpdate();
			}
		}
		template<typename T>
		void StartView(std::function<bool(const e2d::Entity&)> func = 0)
		{
			auto view = m_Scene->rg.view<T>();
			for (auto e : view)
			{
				auto& t = m_Scene->rg.get<T>(e);

				bool filter = true;
				if (func)
				{
					if (t.m_Entity)
					{
						filter = func(*t.m_Entity);
					}
				}
				if (filter)
					t.OnStart();
			}
		}
		template<typename T>
		void DestoryView(std::function<bool(const e2d::Entity&)> func = 0)
		{
			auto view = m_Scene->rg.view<T>();
			for (auto e : view)
			{
				auto& t = m_Scene->rg.get<T>(e);

				bool filter = true;
				if (func)
				{
					if (t.m_Entity)
					{
						filter = func(*t.m_Entity);
					}
				}
				if (filter)

					t.OnDestroy();
			}
		}


		template<typename T>
		void UpdateViewRuntime(std::function<bool(const e2d::Entity&)> func = 0)
		{
			auto view = m_Scene->rg.view<T>();
			for (auto e : view)
			{
				auto& t = m_Scene->rg.get<T>(e);

				bool filter = true;
				if (func)
				{
					if (t.m_Entity)
					{
						filter = func(*t.m_Entity);
					}
				}
				if (filter)
					t.OnUpdateRuntime();
			}
		}
	};

};